#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "tree.h"

#define STR_EQ(s1,s2)	(strcmp(s1,s2)==0)

//常量
char *constant[1024];
Num2 use_constant=0;

//tree链表
treeTable *LinkTree;
treeTable *last_tree;

extern Num4 stack_occupy;

Num2 findConstant(char *str){
    int length=strlen(str);
    char *c = calloc(length, sizeof(char));

    for(int i=0; i<use_constant; i++){
        if(STR_EQ(str, constant[i]) ) return i;
    }
    constant[use_constant++] = strdup(str);
    return (use_constant-1);
}

DataType Token2DataType(enum yytokentype token, enum yytokentype is_f){
    if(is_f==FLOAT && token==NUM4){
        stack_occupy += 4;
        return DATA_TYPE_F_NUMBER_4;
    }
    if(is_f==FLOAT && token==NUM8){
        stack_occupy += 8;
        return DATA_TYPE_F_NUMBER_8;
    }
    switch (token)
    {
        case NUM: stack_occupy++; return DATA_TYPE_NUMBER_1;
        case NUM2: stack_occupy +=2; return DATA_TYPE_NUMBER_2;
        case NUM4: stack_occupy +=4; return DATA_TYPE_NUMBER_4;
        case NUM8: stack_occupy +=8; return DATA_TYPE_NUMBER_8;
        default:exit(0);
    }
}


//创建一个表达式
treeTable *createTreeTab(){
    treeTable *temp = (treeTable *)malloc(sizeof(treeTable));
    return temp;
}
//创建一个表达式
tree *createTree(exprType type){
    tree *temp = (tree *)malloc(sizeof(tree));
    temp->type = type;
    return temp;
}
//链接树
void linkTree(tree *node){
    if(LinkTree){
        last_tree->next = (treeTable *)malloc(sizeof(treeTable));
        treeTable *tmp_tree= last_tree->next;
        tmp_tree->node = node;
        last_tree=tmp_tree;
    }else{
        LinkTree=(treeTable *)malloc(sizeof(treeTable));
        LinkTree->node = node;
        last_tree=LinkTree;
    }
}
//链接树
treeTable * linkTree2(tree *node, treeTable *list){
    
    if(list){
        treeTable * tmp = (treeTable *)malloc(sizeof(treeTable));
        tmp->node = node;
        tmp->next = list;
        list = tmp;
    }else{
        list=(treeTable *)malloc(sizeof(treeTable));
        list->node = node;
    }
    return list;
}
//运算
operation *createOperation(OperationType type, tree *l, tree *r){
    operation *temp = (operation *)malloc(sizeof(operation));
    temp->type=type;
    temp->left=l;
    temp->right=r;
    return temp;
}

//赋值
assign *createAssign(tree *l, tree *r){
    assign *temp = (assign *)malloc(sizeof(assign));
    temp->left=l;
    temp->right=r;
    return temp;
}
funccall *createFunccall(char *name, treeTable *params){
    funccall *temp = (funccall *)malloc(sizeof(funccall));
    temp->name=name;
    temp->params=params;
    return temp;
}
//变量
variable *createVariable(enum yytokentype accuracy, enum yytokentype data_type, char *s, array *arr){
    variable *temp = (variable *)malloc(sizeof(variable));
    temp->type=Token2DataType(data_type, accuracy);
    temp->name=strdup(s);
    temp->arr=arr;
    temp->attr=ATTR_VAR;
    if(temp->type==DATA_TYPE_F_NUMBER_4||temp->type==DATA_TYPE_F_NUMBER_8)
        temp->is_float= 1;
    else
        temp->is_float= 0;
    free(s);
    return temp;
}

//常量
tree *createConstant(DataType type, values *val, array *arr){
    variable *temp = (variable *)malloc(sizeof(variable));
    temp->type=type;
    temp->value=val;
    temp->arr=arr;
    temp->attr=ATTR_CONSTANT;
    tree *tmp_tree = createTree(EXPR_VAR_CONSTANT);
    tmp_tree->entity.var_v = temp;
    return tmp_tree;
}

//值
values *createValues(DataType type, void *data){
    values *temp = (values *)malloc(sizeof(values));
    if(type==DATA_TYPE_STRING){
        temp->string = (Str)data;
    }
    return temp;
}

//编辑数组
array *editArray(array *arr, Num2 number){
    array *temp;
    if(arr==NULL){//创建
        temp = (array *)malloc(sizeof(array));
        temp->layers=1;
        temp->count=number;
        temp->base=(Num2 *)malloc(sizeof(Num2));
        temp->map=(Num2 *)malloc(sizeof(Num2));
        temp->base[0]=number;
        temp->map[0]=1;
    }else{//修改
        temp = arr;
        temp->layers++;
        temp->count +=number;
        temp->base=(Num2 *)realloc(temp->base, temp->layers*sizeof(Num2));
        temp->base[temp->layers-1]=number;
    
        //重新构建map
        free(temp->map);
        temp->map=(Num2 *)calloc( temp->layers, sizeof(Num2));
        temp->map[temp->layers-1]=1;
        for(int i=temp->layers-2; i>=0; --i)
            temp->map[i]= temp->base[i+1] * temp->map[i+1];   
    }
    return temp;
}

variable *mallocVariable(){
    variable *ret = (variable *)malloc(sizeof(variable));
    ret->value = (values *)malloc(sizeof(values));
    return ret;
}

values *createValuesFloat(double num){
    values *temp = (values *)malloc(sizeof(values));
    temp->f_number8=(F64 *)malloc(sizeof(F64));
    temp->f_number8->f=num;
    return temp;
}

double Str2Double(char *str){
    return atof(str);
}
double Var2Double(variable *source){
    if(source->attr==ATTR_RETURN){
        return source->value->f_number8->f;
    }else if(source->type==DATA_TYPE_NUMBER_1){
        return (double)*source->value->number;
    }else if(source->type==DATA_TYPE_NUMBER_2){
        return (double)*source->value->number2;
    }else if(source->type==DATA_TYPE_NUMBER_4){
        return (double)*source->value->number4;
    }else if(source->type==DATA_TYPE_NUMBER_8){
        return (double)*source->value->number8;
    }else if(source->type==DATA_TYPE_F_NUMBER_4){
        return (double)source->value->f_number4->f;
    }else if(source->type==DATA_TYPE_F_NUMBER_8){
        return source->value->f_number8->f;
    }
}